#-------------------------------------------------------------------------------
# Name:        module1
# Purpose:
#
# Author:      ANeslusan
#
# Created:     26/10/2011
# Copyright:   (c) ANeslusan 2011
# Licence:     <your licence>
#-------------------------------------------------------------------------------
#!/usr/bin/env python

import datetime

from sqlalchemy import Column, Integer, String, ForeignKey, Date, Unicode
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref

import functions

Base = declarative_base()

class Product(Base):
    __tablename__ = 'products'
    name = Column(Unicode(256), primary_key=True, autoincrement=False)
    bugs = relationship('Bug', order_by='Bug.bugid', backref='products',
        cascade='all, delete, delete-orphan')
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return '{}: {} bugs'.format(self.name, len(self.bugs))

class Bug(Base):
    __tablename__ = 'bugs'
    bugid = Column(Integer, primary_key=True, autoincrement=False)
    product = Column(Unicode(256), ForeignKey('products.name'))
    opened = Column(Date)
    lifetime = Column(Integer)
    died = Column(Date)
    resolution = Column(Unicode(128))
    status = Column(Unicode(128))
    category = Column(Unicode(256))
    modified = Column(Date)
    priority = Column(Integer)
    severity = Column(Unicode(128))
    changes = relationship('Change', order_by='Change.id', backref='bugs',
        cascade='all, delete, delete-orphan')
    def __init__(self, bugid, product, opened, resolution, status, category,
            modified, priority, severity):
        self.bugid = bugid
        self.product = product
        self.opened = opened
        self.resolution = resolution
        self.status = status
        self.category = category
        self.modified = modified
        self.priority = priority
        self.severity = severity
        self.died = datetime.date.min
        self.lifetime = self.life()
    def __repr__(self):
        return 'Bug {}: {}, Opened on {}'.format(self.bugid, self.product,
            self.opened)
    def life(self):
        # Updating the bug's lifetime
        if not self.changes:
            return -1
        else:
            dead = False
            changed = datetime.date.min
            for change in self.changes:
                if change.what == 'Status' and change.added == 'VERIFIED':
                    if change.when >= changed:
                        dead = True
                        changed = change.when
                elif change.what == 'Status' and change.added == 'CLOSED':
                    if change.when >= changed:
                        dead = True
                        changed = change.when
                elif change.what == 'Status' and change.added == 'RESOLVED':
                    if change.when >= changed:
                        dead = True
                        changed = change.when
                elif change.what == 'Status' and change.added == 'REOPENED':
                    if change.when >= changed:
                        dead = False
                        changed = change.when
                elif change.what == 'Status' and change.added == 'NEW':
                    if change.when >= changed:
                        dead = False
                        changed = change.when
            if not dead:
                return -1
            else:
                died = datetime.date.min
                resolution_changed = False
                for change in self.changes:
                    if change.what == 'Resolution':
                        resolution_changed = True
                        if change.when > died:
                            died = change.when
                    if change.what == 'Status' and not resolution_changed:
                        if change.when > died:
                            died = change.when
                if died > datetime.date.min:
                    self.lifetime = (died - self.opened).days
                    self.died = died
                    return self.lifetime
                else:
                    return -1
    def was_open(self, date):
        if not self.changes:
            return True
        elif date < self.opened:
            return False
        elif date > self.died:
            return False
        else:
            return True

class Change(Base):
    __tablename__ = 'bugchanges'
    id = Column(Integer, primary_key=True)
    who = Column(Unicode(256))
    when = Column(Date)
    what = Column(Unicode(256))
    removed = Column(Unicode(512))
    added = Column(Unicode(512))
    bugid = Column(Integer, ForeignKey('bugs.bugid'))
    def __init__(self, who, when, what, removed, added):
        self.who = who
        self.when = when
        self.what = what
        self.removed = removed
        self.added = added
    def __repr__(self):
        return 'Who: {}; When: {}; What: {}; Removed: {}; Added: {}'.format(
            self.who, self.when, self.what, self.removed, self.added)

def main():
    Base.metadata.create_all(functions.engine)

if __name__ == '__main__':
    main()
